#include "app_uartDMA.h"
 QueueHandle_t xRxQueue;                // 接收数据队列
 SemaphoreHandle_t xRxBufferMutex;      // 缓冲区互斥锁

// 配置参数（根据实际硬件修改）
#define FLASH_SHARED_SECTOR    40U          // 所有数据共享的扇区号（固定一个扇区）
#define MAX_INDEX              (EFM_SECTOR_SIZE - 1)  // 最大索引（0~4095 for 4KB扇区）

// 静态数组缓存扇区数据（全局区，避免栈溢出）
static uint32_t g_sector_data[EFM_SECTOR_SIZE / 4];

uint8_t m_au8RxBuf[100];
uint8_t m_au8TxBuf[APP_TX_LEN_MAX];

// static void Timer61Init(void);

//只获取一次IMEI信息
uint8_t IMEI_FLAG = 1;


UartHandle_t uart_handle = {
    
    .send_data = USART_SendData_DMA,
};

uint8_t otaflag = 0;

//获取OTA标志位
uint8_t get_otaflag(void)
{
    return otaflag;
}

//改变OTA标志位
void set_otaflag(uint8_t flag)
{
    otaflag = flag;
}

char dmarxdatap[QUENEDATAMAXLEN];

//获取OTA标志
void check_for_OTA_simple(uint8_t *pData, uint16_t u16Len);
//获取IMEI信息
void get_IMEI(uint8_t *pData, uint16_t u16Len);

static __IO en_flag_status_t m_enRxFrameEnd;
static __IO uint16_t m_u16RxLen;

/*******************************************************************************
 * Function implementation - global ('extern') and local ('static')
 ******************************************************************************/

/**
 * @brief  DMA transfer complete IRQ callback function.
 * @param  None
 * @retval None
 */

// void USART_SendData_DMA(uint8_t *pData, uint16_t len)
// {
//     if ((pData == NULL) || (len == 0)) {
//         return;  // 避免缓冲区溢出
//     }

//     // 复制数据到TX缓冲区
//     memcpy(m_au8TxBuf, pData, len);

//     // 配置TX DMA参数
//     DMA_SetTransCount(TX_DMA_UNIT, TX_DMA_CH, len);
//     DMA_SetBlockSize(TX_DMA_UNIT, TX_DMA_CH, 1);
//     DMA_SetSrcAddr(TX_DMA_UNIT, TX_DMA_CH, (uint32_t)(&m_au8TxBuf[0]));

//     // 启用DMA通道和USART发送
//     DMA_ChCmd(TX_DMA_UNIT, TX_DMA_CH, ENABLE);
//     USART_FuncCmd(CM_USART1, USART_TX, ENABLE); 
// }

void USART_SendData_DMA(uint8_t *pData, uint16_t len) {
    // 参数校验
    if ((pData == NULL) || (len == 0) || (len > ARRAY_SZ(m_au8TxBuf))) {
        return;
    }

    // 复制数据到TX缓冲区
    memcpy(m_au8TxBuf, pData, len);

    // 配置DMA前禁用通道
    DMA_ChCmd(TX_DMA_UNIT, TX_DMA_CH, DISABLE);

    // 设置DMA参数
    DMA_SetTransCount(TX_DMA_UNIT, TX_DMA_CH, len);
    DMA_SetBlockSize(TX_DMA_UNIT, TX_DMA_CH, 1);
    DMA_SetSrcAddr(TX_DMA_UNIT, TX_DMA_CH, (uint32_t)m_au8TxBuf);

    // 重新启用DMA和USART TX
    DMA_ChCmd(TX_DMA_UNIT, TX_DMA_CH, ENABLE);
    USART_FuncCmd(CM_USART1, USART_TX, DISABLE);
    USART_FuncCmd(CM_USART1, USART_TX, ENABLE);
}

uint8_t wifi_mac[6] = {0};  // 全局MAC地址数组
// uint8_t MAC_FLAG = 1;

uint8_t IMEI_arr[6] = {0};
static void RX_DMA_TC_IrqCallback(void)
{

    // USART_SendData_DMA(m_au8RxBuf,30);
    // check_for_OTA_simple(m_au8RxBuf, 20);
    // get_IMEI(m_au8RxBuf,30);
    // USART_SendData_DMA(IMEI_arr, 12);
    m_u16RxLen = APP_FRAME_LEN_MAX;
    m_enRxFrameEnd = SET;

    DMA_ClearTransCompleteStatus(RX_DMA_UNIT, RX_DMA_TC_FLAG);

     // 重置DMA接收配置
    DMA_SetDestAddr(RX_DMA_UNIT, RX_DMA_CH, (uint32_t)m_au8RxBuf);
    DMA_SetTransCount(RX_DMA_UNIT, RX_DMA_CH, APP_FRAME_LEN_MAX);
    DMA_ChCmd(RX_DMA_UNIT, RX_DMA_CH, ENABLE);
}



/**
 * @brief  DMA transfer complete IRQ callback function.
 * @param  None
 * @retval None
 */
static void TX_DMA_TC_IrqCallback(void)
{
    USART_FuncCmd(USART_UNIT, USART_INT_TX_CPLT, ENABLE);

    DMA_ClearTransCompleteStatus(TX_DMA_UNIT, TX_DMA_TC_FLAG);

    
}


static int32_t DMA_Config(void)
{
    int32_t i32Ret;
    stc_dma_init_t stcDmaInit;
    stc_irq_signin_config_t stcIrqSignConfig;

    /* DMA&AOS FCG enable */
    RX_DMA_FCG_ENABLE();
    TX_DMA_FCG_ENABLE();
    FCG_Fcg0PeriphClockCmd(FCG0_PERIPH_AOS, ENABLE);

    /* USART_RX_DMA */
    (void)DMA_StructInit(&stcDmaInit);
    stcDmaInit.u32IntEn = DMA_INT_ENABLE;
    stcDmaInit.u32BlockSize = 1UL;
    stcDmaInit.u32TransCount = APP_FRAME_LEN_MAX;
    stcDmaInit.u32DataWidth = DMA_DATAWIDTH_8BIT;
    stcDmaInit.u32DestAddr = (uint32_t)&m_au8RxBuf[0];  // 初始地址为缓冲区起始位置
    stcDmaInit.u32SrcAddr = (uint32_t)(&USART_UNIT->RDR);
    stcDmaInit.u32SrcAddrInc = DMA_SRC_ADDR_FIX;
    stcDmaInit.u32DestAddrInc = DMA_DEST_ADDR_INC;
    i32Ret = DMA_Init(RX_DMA_UNIT, RX_DMA_CH, &stcDmaInit);
    if (LL_OK == i32Ret) {
        stcIrqSignConfig.enIntSrc = RX_DMA_TC_INT_SRC;
        stcIrqSignConfig.enIRQn  = RX_DMA_TC_IRQn;
        stcIrqSignConfig.pfnCallback = &RX_DMA_TC_IrqCallback;
        (void)INTC_IrqSignIn(&stcIrqSignConfig);
        NVIC_ClearPendingIRQ(stcIrqSignConfig.enIRQn);
        NVIC_SetPriority(stcIrqSignConfig.enIRQn, DDL_IRQ_PRIO_08);
        NVIC_EnableIRQ(stcIrqSignConfig.enIRQn);

        AOS_SetTriggerEventSrc(RX_DMA_TRIG_SEL, RX_DMA_TRIG_EVT_SRC);

        DMA_Cmd(RX_DMA_UNIT, ENABLE);
        DMA_TransCompleteIntCmd(RX_DMA_UNIT, RX_DMA_TC_INT, ENABLE);
        (void)DMA_ChCmd(RX_DMA_UNIT, RX_DMA_CH, ENABLE);
    }

    /* USART_TX_DMA */
    // 发送部分保持不变
    (void)DMA_StructInit(&stcDmaInit);
    stcDmaInit.u32IntEn = DMA_INT_ENABLE;
    stcDmaInit.u32BlockSize = 1UL;
    stcDmaInit.u32TransCount = ARRAY_SZ(m_au8TxBuf);
    stcDmaInit.u32DataWidth = DMA_DATAWIDTH_8BIT;
    stcDmaInit.u32DestAddr = (uint32_t)(&USART_UNIT->TDR);
    stcDmaInit.u32SrcAddr = (uint32_t)m_au8TxBuf;
    stcDmaInit.u32SrcAddrInc = DMA_SRC_ADDR_INC;
    stcDmaInit.u32DestAddrInc = DMA_DEST_ADDR_FIX;
    i32Ret = DMA_Init(TX_DMA_UNIT, TX_DMA_CH, &stcDmaInit);
    if (LL_OK == i32Ret) {
        stcIrqSignConfig.enIntSrc = TX_DMA_TC_INT_SRC;
        stcIrqSignConfig.enIRQn  = TX_DMA_TC_IRQn;
        stcIrqSignConfig.pfnCallback = &TX_DMA_TC_IrqCallback;
        (void)INTC_IrqSignIn(&stcIrqSignConfig);
        NVIC_ClearPendingIRQ(stcIrqSignConfig.enIRQn);
        NVIC_SetPriority(stcIrqSignConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
        NVIC_EnableIRQ(stcIrqSignConfig.enIRQn);

        AOS_SetTriggerEventSrc(TX_DMA_TRIG_SEL, TX_DMA_TRIG_EVT_SRC);

        DMA_Cmd(TX_DMA_UNIT, ENABLE);
        DMA_TransCompleteIntCmd(TX_DMA_UNIT, TX_DMA_TC_INT, ENABLE);
    }

    return i32Ret;
}

/**
 * @brief  Configure TMR0.
 * @param  [in] u16TimeoutBits:         Timeout bits
 * @retval None
 */
static void TMR0_Config(uint16_t u16TimeoutBits)
{
    uint16_t u16Div;
    uint16_t u16Delay;
    uint16_t u16CompareValue;
    stc_tmr0_init_t stcTmr0Init;

    TMR0_FCG_ENABLE();

    /* Initialize TMR0 base function. */
    stcTmr0Init.u32ClockSrc = TMR0_CLK_SRC_XTAL32;
    stcTmr0Init.u32ClockDiv = TMR0_CLK_DIV8;
    stcTmr0Init.u32Func     = TMR0_FUNC_CMP;
    if (TMR0_CLK_DIV1 == stcTmr0Init.u32ClockDiv) {
        u16Delay = 7U;
    } else if (TMR0_CLK_DIV2 == stcTmr0Init.u32ClockDiv) {
        u16Delay = 5U;
    } else if ((TMR0_CLK_DIV4 == stcTmr0Init.u32ClockDiv) || \
               (TMR0_CLK_DIV8 == stcTmr0Init.u32ClockDiv) || \
               (TMR0_CLK_DIV16 == stcTmr0Init.u32ClockDiv)) {
        u16Delay = 3U;
    } else {
        u16Delay = 2U;
    }

    u16Div = (uint16_t)1U << (stcTmr0Init.u32ClockDiv >> TMR0_BCONR_CKDIVA_POS);
    u16CompareValue = ((u16TimeoutBits + u16Div - 1U) / u16Div) - u16Delay;
    stcTmr0Init.u16CompareValue = u16CompareValue;
    (void)TMR0_Init(TMR0_UNIT, TMR0_CH, &stcTmr0Init);

    TMR0_HWStartCondCmd(TMR0_UNIT, TMR0_CH, ENABLE);
    TMR0_HWClearCondCmd(TMR0_UNIT, TMR0_CH, ENABLE);
}

/**
 * @brief  Stop timeout timer.
 * @param  [in]  TMR0x                  Pointer to TMR0 instance register base.
 *                                      This parameter can be a value of the following:
 *   @arg  CM_TMR0_x or CM_TMR0
 * @param  [in]  u32Ch                  TMR0 channel.
 *                                      This parameter can be a value @ref TMR0_Channel
 */
static void USART_StopTimeoutTimer(CM_TMR0_TypeDef *TMR0x, uint32_t u32Ch)
{

    uint32_t u32ClrMask;
    uint32_t u32SetMask;
    uint32_t u32BitOffset;

    u32BitOffset = 16UL * u32Ch;

    /* Set: TMR0_BCONR.SYNCLKA<B>=1, TMR0_BCONR.SYNA<B>=0 */
    u32ClrMask = (TMR0_BCONR_SYNCLKA | TMR0_BCONR_SYNSA) << u32BitOffset;
    u32SetMask = TMR0_BCONR_SYNCLKA << u32BitOffset;
    MODIFY_REG32(TMR0x->BCONR, u32ClrMask, u32SetMask);

    /* Set: TMR0_BCONR.CSTA<B>=0, TMR0_BCONR.SYNCLKA<B>=0, TMR0_BCONR.SYNSA<B>=1 */
    u32ClrMask = (TMR0_BCONR_SYNCLKA | TMR0_BCONR_SYNSA | TMR0_BCONR_CSTA) << u32BitOffset;
    u32SetMask = TMR0_BCONR_SYNSA << u32BitOffset;
    MODIFY_REG32(TMR0x->BCONR, u32ClrMask, u32SetMask);
}

//回传参数0
uint8_t out_bed_parameter;
//回传参数1
uint8_t out_bed_warn;
//回传参数2
uint8_t sit_up_warn;

//提供接口给实时数据 获取
uint8_t get_out_bed_parameter(void)
{
    return out_bed_parameter;
}
//提供接口给实时数据 获取
 uint8_t get_out_bed_warn(void)
{
    return out_bed_warn;
}
//提供接口给实时数据 获取
 uint8_t get_sit_up_warn(void)
{
    return sit_up_warn;
}

//接收标志
// uint8_t receive_flag = 0;



/// @brief 设置回传标志 
typedef enum{
    NONE = 0,
    OUT_BED_PARAMETER,
    OUT_BED_WARN,
    SIT_UP_WARN
}Flash_Flag;

//接收标志
uint8_t  enum_flag = NONE;

uint8_t outarr[3] = {0};

void Change_ReceiveFlag(Flash_Flag data) {
    enum_flag = data;
}

/**
 * @brief //获取OTA标志(优化版本)
 * @param  None
 * @retval None
 */
void check_for_OTA_simple(uint8_t *pData, uint16_t u16Len)
{
    if(pData != NULL && u16Len > 0){
        // E0为OTA标志
        if (pData[2] == 0x00 && pData[3] == 0x10)
        {
            set_otaflag(1);
        }
    }
}

void get_passback_data(uint8_t *pData, uint16_t u16Len)
{
    if(pData != NULL && u16Len > 0){
        
        if (pData[2] == 0x00 && pData[9] == 0x03 && pData[10] == 0xFC)
        {
            switch (pData[11])
            {
            case 0:
                /* code */
                out_bed_parameter = pData[12];
                Change_ReceiveFlag(OUT_BED_PARAMETER);
                break;
            case 1:
                /* code */
                out_bed_warn = pData[12];
                Change_ReceiveFlag(OUT_BED_WARN);
                break;
            
            case 2:
                /* code */
                sit_up_warn = pData[12];
                Change_ReceiveFlag(SIT_UP_WARN);
                break;
                    
            default:
                break;
            }
            

        }
    }
}


/**
 * @brief  写入数据到Flash
 * @param  u32Data: 待写入的32位数据
 * @retval 成功=0，失败=错误码
 */
// 选择安全的 Flash 存储地址（扇区10内的偏移地址）
// #define FLASH_DATA_SECTOR    (40U)
// #define FLASH_DATA_ADDR      (EFM_SECTOR_ADDR(FLASH_DATA_SECTOR))
// #define FLASH_OFFSET(n)    ((n) * 4U)  // 每个数据项偏移4字节
#define FLASH_SECTOR(n)    (40U + (n))  // 扇区40、41、42..
// void Flash_Init(void)
// {
//     /* 使能外设寄存器写操作 */
//     LL_PERIPH_WE(LL_PERIPH_EFM);
    
//     /* 等待Flash就绪 */
//     en_int_status_t flag1, flag2;
//     do {
//         flag1 = EFM_GetStatus(EFM_FLAG_RDY);
//         flag2 = EFM_GetStatus(EFM_FLAG_RDY1);
//     } while ((SET != flag1) || (SET != flag2));
    
//     /* 使能EFM写操作 */
//     EFM_FWMC_Cmd(ENABLE);
// }

/**
 * @brief  初始化Flash（系统启动时调用一次）
 * @return 成功返回1，失败返回0
 */
uint8_t Flash_Init(void) {
    /* 使能外设寄存器写操作 */
    LL_PERIPH_WE(LL_PERIPH_EFM);
    
    /* 等待Flash就绪 */
    en_int_status_t flag1, flag2;
    uint32_t timeout = 0;
    do {
        flag1 = EFM_GetStatus(EFM_FLAG_RDY);
        flag2 = EFM_GetStatus(EFM_FLAG_RDY1);
        timeout++;
    } while (((SET != flag1) || (SET != flag2)) && (timeout < 10000));  // 增加超时保护
    
    if (timeout >= 10000) {
        LL_PERIPH_WP(LL_PERIPH_EFM);  // 关闭写使能
        return 0;  // 初始化超时失败
    }
    
    /* 使能EFM写操作 */
    EFM_FWMC_Cmd(ENABLE);
    
    /* 关闭外设写保护（仅在需要修改寄存器时再打开） */
    LL_PERIPH_WP(LL_PERIPH_EFM);
    return 1;  // 初始化成功
}


// 定义互斥锁
SemaphoreHandle_t xFlashMutex;
// 擦除整个扇区（必须在使用前执行）
// 写入uint8_t数据（指定位置）


// void Flash_WriteU8(uint8_t index, uint8_t data) {

//         Flash_Init();
//         uint32_t sector = FLASH_SECTOR(index);
//         uint32_t addr = EFM_SECTOR_ADDR(sector);  // 获取扇区起始地址
//         uint32_t write_data = 0xFFFFFF00 | data;   // 低8位为有效数据
    
//         // 解锁扇区操作
//         EFM_SingleSectorOperateCmd(sector, ENABLE);
        
//         // 擦除整个扇区（确保数据为0xFF）
//         if (LL_OK != EFM_SectorErase(addr)) {
//             EFM_SingleSectorOperateCmd(sector, DISABLE);
//             return;  // 擦除失败，退出
//         }
        
//         // 写入数据（4字节对齐）
//         if (LL_OK != EFM_ProgramWord(addr, write_data)) {
//             EFM_SingleSectorOperateCmd(sector, DISABLE);
//             return;  // 写入失败，退出
//         }
        
//         // 锁定扇区
//         EFM_SingleSectorOperateCmd(sector, DISABLE);

// }

//第一版
// void Flash_WriteU8(uint8_t index, uint8_t data) {
//     Flash_Init();
//     uint32_t sector = FLASH_SECTOR(index);
//     uint32_t addr = EFM_SECTOR_ADDR(sector);
    
//     // 1. 读取整个扇区数据
//     uint32_t sector_data[EFM_SECTOR_SIZE / 4];
//     if (LL_OK != EFM_ReadByte(addr, (uint8_t*)sector_data, sizeof(sector_data))) {
//         EFM_SingleSectorOperateCmd(sector, DISABLE);
//         return;
//     }
    
//     // 2. 修改目标字节（每4个uint8_t共享一个uint32_t）
//     uint32_t word_idx = index / 4;           // 计算目标uint32_t的索引
//     uint32_t byte_offset = index % 4;        // 计算字节在uint32_t中的偏移
//     uint32_t mask = ~(0xFFu << (byte_offset * 8));
//     sector_data[word_idx] = (sector_data[word_idx] & mask) | ((uint32_t)data << (byte_offset * 8));
    
//     // 3. 擦除扇区
//     EFM_SingleSectorOperateCmd(sector, ENABLE);
//     if (LL_OK != EFM_SectorErase(addr)) {
//         EFM_SingleSectorOperateCmd(sector, DISABLE);
//         return;
//     }
    
//     // 4. 写回整个扇区数据
//     for (uint32_t i = 0; i < EFM_SECTOR_SIZE / 4; i++) {
//         if (LL_OK != EFM_ProgramWord(addr + i * 4, sector_data[i])) {
//             EFM_SingleSectorOperateCmd(sector, DISABLE);
//             return;
//         }
//     }
    
//     EFM_SingleSectorOperateCmd(sector, DISABLE);
// }


// void Flash_ReadU8(uint8_t index, uint8_t *data) {
//     if (data == NULL) return;
    
//     uint32_t sector = FLASH_SECTOR(index);
//     uint32_t addr = EFM_SECTOR_ADDR(sector);
//     uint32_t read_data;
    
//     // 计算目标uint32_t的地址（与写入逻辑一致）
//     uint32_t word_addr = addr + (index / 4) * 4;
    
//     // 读取4字节数据
//     if (LL_OK != EFM_ReadByte(word_addr, (uint8_t*)&read_data, sizeof(read_data))) {
//         return;  // 读取失败
//     }
    
//     // 提取目标字节（与写入逻辑一致）
//     uint32_t byte_offset = index % 4;
//     *data = (uint8_t)((read_data >> (byte_offset * 8)) & 0xFF);
// }
//第一版end


/**
 * @brief  从Flash读取一个字节
 * @param  index: 数据索引（0 ~ MAX_INDEX，即0 ~ 4095 for 4KB扇区）
 * @param  data: 输出参数，存储读取到的字节
 * @return 成功返回1，失败返回0（索引越界/读取失败）
 */
uint8_t Flash_ReadU8(uint8_t index, uint8_t *data) {
    if ((data == NULL) || (index > MAX_INDEX)) {
        return 0;  // 空指针或索引越界
    }
    
    // 计算扇区起始地址和目标字节所在的4字节地址
    uint32_t sector = FLASH_SHARED_SECTOR;
    uint32_t sector_addr = EFM_SECTOR_ADDR(sector);  // 扇区起始地址 = 扇区大小 × 扇区号
    // 4（0100） & ~0x3（1100） 0100
    uint32_t word_addr = sector_addr + (index & ~0x3);  // 目标字节所在的4字节块地址（对齐到4字节）
    
    // 读取4字节数据
    uint32_t read_data;
    if (LL_OK != EFM_ReadByte(word_addr, (uint8_t*)&read_data, sizeof(read_data))) {
        return 0;  // 读取失败
    }
    
    // 提取目标字节（计算偏移）
    uint32_t byte_offset = index % 4;
    *data = (uint8_t)((read_data >> (byte_offset * 8)) & 0xFF);
    return 1;  // 读取成功
}


/**
 * @brief  向Flash写入一个字节
 * @param  index: 数据索引（0 ~ MAX_INDEX，即0 ~ 4095 for 4KB扇区）
 * @param  data: 要写入的字节
 * @return 成功返回1，失败返回0（索引越界/擦除失败/写入失败）
 */
uint8_t Flash_WriteU8(uint8_t index, uint8_t data) {

    if (index > MAX_INDEX) {
        return 0;  // 索引越界（超过扇区容量）
    }
    
    uint32_t sector = FLASH_SHARED_SECTOR;
    uint32_t sector_addr = EFM_SECTOR_ADDR(sector);  // 扇区起始地址
    
    // 1. 临时打开外设写使能（修改EFM寄存器需要）
    LL_PERIPH_WE(LL_PERIPH_EFM);
    
    // 2. 读取整个扇区数据到缓存（备份原有数据）
    if (LL_OK != EFM_ReadByte(sector_addr, (uint8_t*)g_sector_data, sizeof(g_sector_data))) {
        LL_PERIPH_WP(LL_PERIPH_EFM);  // 关闭写使能
        return 0;  // 读取扇区失败
    }
    
    // 3. 在缓存中修改目标字节（位运算）
    uint32_t word_idx = index / 4;           // 目标字节所在的uint32_t索引
    uint32_t byte_offset = index % 4;        // 字节在uint32_t中的偏移（0~3）
    //11111111 11111111 00000000 11111111
    uint32_t mask = ~(0xFFu << (byte_offset * 8));  // 清除目标字节的掩码
    g_sector_data[word_idx] = (g_sector_data[word_idx] & mask) | ((uint32_t)data << (byte_offset * 8));
    
    // 4. 擦除扇区（必须先擦除才能写入）
    EFM_SingleSectorOperateCmd(sector, ENABLE);
    if (LL_OK != EFM_SectorErase(sector_addr)) {  // 擦除扇区（传入扇区起始地址）
        EFM_SingleSectorOperateCmd(sector, DISABLE);
        LL_PERIPH_WP(LL_PERIPH_EFM);
        return 0;  // 擦除失败
    }
    
    // 5. 将修改后的缓存数据写回扇区（按4字节编程）
    uint8_t write_ok = 1;
    for (uint32_t i = 0; i < (EFM_SECTOR_SIZE / 4); i++) {
        if (LL_OK != EFM_ProgramWord(sector_addr + i * 4, g_sector_data[i])) {
            write_ok = 0;
            break;
        }
    }
    
    // 6. 关闭扇区操作和外设写使能
    EFM_SingleSectorOperateCmd(sector, DISABLE);
    LL_PERIPH_WP(LL_PERIPH_EFM);  // 关闭外设写保护
    
    // 7. 写后校验（可选，增强可靠性）
    // if (write_ok) {
    //     uint8_t verify_data;
    //     if (Flash_ReadU8(index, &verify_data) && (verify_data == data)) {
    //         return 1;  // 写入并校验成功
    //     } else {
    //         return 0;  // 写入后校验失败
    //     }
    // } else {
    //     return 0;  // 写入过程失败
    // }
}

static void USART_RxTimeout_IrqCallback(void)
{

    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    RxDataMsg msg;
    // 清除超时标志
    USART_StopTimeoutTimer(TMR0_UNIT, TMR0_CH);
    USART_ClearStatus(USART_UNIT, USART_FLAG_RX_TIMEOUT);

    m_enRxFrameEnd = SET;

         
        //  outarr[0] = out_bed_parameter;
		//  outarr[1] = out_bed_warn;
		//  outarr[2] = sit_up_warn;
         
        // USART_SendData_DMA(outarr, 3);

        //===========================start===========================

        //  // 1. 计算实际接收长度
        //  uint16_t u16ReceivedLen = APP_FRAME_LEN_MAX - DMA_GetTransCount(RX_DMA_UNIT, RX_DMA_CH);
        
        //  // 2. 处理数据（如校验、存储）
        //  if (u16ReceivedLen > 0) 
        //  {
        //      ProcessData(m_au8RxBuf, u16ReceivedLen);  // 自定义处理函数
        //  }
         
        // USART_SendData_DMA(m_au8RxBuf, APP_FRAME_LEN_MAX);
         // 3. 重置DMA（必须！）
         DMA_ChCmd(RX_DMA_UNIT, RX_DMA_CH, DISABLE);
         DMA_SetDestAddr(RX_DMA_UNIT, RX_DMA_CH, (uint32_t)m_au8RxBuf);
         DMA_SetTransCount(RX_DMA_UNIT, RX_DMA_CH, APP_FRAME_LEN_MAX);
         DMA_ChCmd(RX_DMA_UNIT, RX_DMA_CH, ENABLE);

         //USART_SendData_DMA(m_au8RxBuf, APP_FRAME_LEN_MAX);
        //===========================end===========================


         // 锁定缓冲区，复制数据到临时存储（避免任务处理时被中断修改）
    if (xSemaphoreTakeFromISR(xRxBufferMutex, &xHigherPriorityTaskWoken) == pdTRUE) {
        msg.pData = m_au8RxBuf;
        msg.u16Len = m_u16RxLen;
        xSemaphoreGiveFromISR(xRxBufferMutex, &xHigherPriorityTaskWoken);
    }

    // 将数据入队（中断安全版本）
    if (xQueueSendFromISR(xRxQueue, &msg, &xHigherPriorityTaskWoken) != pdTRUE) {
        // 队列满处理（可选）
    }

        // 重置DMA为下次接收
        // memset(m_au8RxBuf, 0, APP_FRAME_LEN_MAX);
        DMA_SetTransCount(RX_DMA_UNIT, RX_DMA_CH, APP_FRAME_LEN_MAX);
        DMA_ChCmd(RX_DMA_UNIT, RX_DMA_CH, ENABLE);

        // 触发任务切换
        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}


// static void USART2_RxTimeout_IrqCallback(void)
// {

//     // USART_StopTimeoutTimer(TMR0_UNIT, TMR0_CH);

//     USART_ClearStatus(USART_UNIT2, USART_FLAG_RX_TIMEOUT);
// }

void get_heartbeat(uint8_t *pData, uint16_t u16Len)
{
    if(pData != NULL && u16Len > 0){
        // E0为OTA标志
        if (pData[2] == 0x00 && pData[3] == 0x21)
        {
            uint8_t start_ota[12] = {0x55, 0xAA, 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00,0xFE};
			start_ota[5] = pData[5];	
            USART_SendData_DMA(start_ota, 12);
        }
    }
}

void get_IMEI(uint8_t *pData, uint16_t u16Len)
{
    if(pData != NULL && u16Len > 0){
        // E0为OTA标志
        if (pData[2] == 0x80 && pData[3] == 0x12)
        {
            uint8_t imei[12] = {0};
            for (uint8_t i = 0; i < 12; i++)
            {
                //接收4g返回的imei
                imei[i] = m_au8RxBuf[i+13]-0x30;
            } 
          for (uint8_t i = 0; i < 6; i++) {

            IMEI_arr[i] = imei[2 * i] * 16 + imei[2 * i + 1];    
                // USART_SendData_DMA(IMEI_arr, 6);

            }

        }
    }
}
//回传数据判断参数
void uart_process_task(void *pvParameters)
{
    RxDataMsg msg;

    for (;;) {
        // 从队列获取数据（阻塞等待）
        if (xQueueReceive(xRxQueue, &msg, portMAX_DELAY) == pdTRUE) {
            // 加锁访问共享缓冲区
            if (xSemaphoreTake(xRxBufferMutex, portMAX_DELAY) == pdTRUE) {

                if(IMEI_FLAG){
                get_IMEI(msg.pData, msg.u16Len);
                }

                //处理回传数据
                get_passback_data(msg.pData, msg.u16Len);
                // 处理 OTA 检测（使用状态机或单次扫描）
                check_for_OTA_simple(msg.pData, msg.u16Len); // 修改函数参数为接收数据

                // get_heartbeat(msg.pData, msg.u16Len);

                xSemaphoreGive(xRxBufferMutex);
            }
        }
    }
}

//接收回传数据写入flash任务
void get_passbackflash_task(void *pvParameters)
{
    //上电读一次 读取flash数据
    Flash_ReadU8(0,&out_bed_parameter);
    Flash_ReadU8(1,&out_bed_warn);
    Flash_ReadU8(2,&sit_up_warn);
    if (out_bed_parameter == 0xFF ||  out_bed_warn == 0xFF || sit_up_warn == 0xFF)
        {
            out_bed_parameter = 0;
            out_bed_warn  = 0;
            sit_up_warn = 0;
        }

    nczallcode_U.threshold_factor  = out_bed_parameter;
    nczallcode_U.continuous_on_bed_duration_minutes = out_bed_warn;
    nczallcode_U.unlock_sitting_alarm_duration_minutes  = sit_up_warn;

    while (1)
    {
        // outarr[0] = out_bed_parameter;
		//  outarr[1] = out_bed_warn;
		//  outarr[2] = sit_up_warn;
         
        // USART_SendData_DMA(&out_bed_parameter, 1);
        //  等待接收数据
        if (enum_flag!=0)
        {
           
           if (enum_flag == OUT_BED_PARAMETER)
           {
            nczallcode_U.threshold_factor  = out_bed_parameter;
            Flash_WriteU8(0,out_bed_parameter);
            // Flash_ReadU8(0,&out_bed_parameter);
            //  USART_SendData_DMA(&out_bed_parameter, 1);
           }else if (enum_flag == OUT_BED_WARN)
           {
            nczallcode_U.continuous_on_bed_duration_minutes = out_bed_warn;
            Flash_WriteU8(1,out_bed_warn);
            // Flash_ReadU8(1,&out_bed_warn);
           }else if (enum_flag == SIT_UP_WARN)
           {
            nczallcode_U.unlock_sitting_alarm_duration_minutes  = sit_up_warn;
            Flash_WriteU8(2,sit_up_warn);
            // Flash_ReadU8(2,&sit_up_warn);
           }
           enum_flag = NONE;
        }

         //获取堆栈调用状况
			// UBaseType_t uxHighWaterMark;
            //     uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);

            //       char stack_info[100];
            //     sprintf(stack_info, "Stack Usage: %u bytes\r\n", uxHighWaterMark);
                
            //     // 先发送堆栈信息
            //     USART_SendData_DMA((uint8_t*)stack_info, strlen(stack_info));
        vTaskDelay(2000);
    }
}



/**
 * @brief  USART TX complete IRQ callback function.
 * @param  None
 * @retval None
 */
static void USART_TxComplete_IrqCallback(void)
{
    USART_FuncCmd(USART_UNIT, (USART_TX | USART_INT_TX_CPLT), DISABLE);
}


// static void USART2_TxComplete_IrqCallback(void)
// {
//     USART_FuncCmd(USART_UNIT2, (USART_TX | USART_INT_TX_CPLT), DISABLE);
// }

/**
 * @brief  USART RX error IRQ callback.
 * @param  None
 * @retval None
 */
static void USART_RxError_IrqCallback(void)
{
    (void)USART_ReadData(USART_UNIT);

    USART_ClearStatus(USART_UNIT, (USART_FLAG_PARITY_ERR | USART_FLAG_FRAME_ERR | USART_FLAG_OVERRUN));
}

// static void USART2_RxError_IrqCallback(void)
// {
//     (void)USART_ReadData(USART_UNIT2);

//     USART_ClearStatus(USART_UNIT2, (USART_FLAG_PARITY_ERR | USART_FLAG_FRAME_ERR | USART_FLAG_OVERRUN));
// }
void App_uart_init(void){

    uart_handle.uartqueue = xQueueCreate(10,30);

    stc_usart_uart_init_t stcUartInit;
    stc_irq_signin_config_t stcIrqSigninConfig;
    /* Enable peripheral clock */
    USART_FCG_ENABLE();

    /* Initialize UART. */
    (void)USART_UART_StructInit(&stcUartInit);
    stcUartInit.u32ClockDiv = USART_CLK_DIV64;
    stcUartInit.u32CKOutput = USART_CK_OUTPUT_ENABLE;
    stcUartInit.u32Baudrate = USART_BAUDRATE;
    stcUartInit.u32OverSampleBit = USART_OVER_SAMPLE_8BIT;
    if (LL_OK != USART_UART_Init(USART_UNIT, &stcUartInit, NULL)) {
        BSP_LED_On(LED_RED);
        for (;;) {
        }
    }

    /* Register TX complete IRQ handler. */
    stcIrqSigninConfig.enIRQn = USART_TX_CPLT_IRQn;
    stcIrqSigninConfig.enIntSrc = USART_TX_CPLT_INT_SRC;
    stcIrqSigninConfig.pfnCallback = &USART_TxComplete_IrqCallback;
    (void)INTC_IrqSignIn(&stcIrqSigninConfig);
    NVIC_ClearPendingIRQ(stcIrqSigninConfig.enIRQn);
    NVIC_SetPriority(stcIrqSigninConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
    NVIC_EnableIRQ(stcIrqSigninConfig.enIRQn);

    /* Register RX error IRQ handler. */
    stcIrqSigninConfig.enIRQn = USART_RX_ERR_IRQn;
    stcIrqSigninConfig.enIntSrc = USART_RX_ERR_INT_SRC;
    stcIrqSigninConfig.pfnCallback = &USART_RxError_IrqCallback;
    (void)INTC_IrqSignIn(&stcIrqSigninConfig);
    NVIC_ClearPendingIRQ(stcIrqSigninConfig.enIRQn);
    NVIC_SetPriority(stcIrqSigninConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
    NVIC_EnableIRQ(stcIrqSigninConfig.enIRQn);

    /* Register RX timeout IRQ handler. */
    stcIrqSigninConfig.enIRQn = USART_RX_TIMEOUT_IRQn;
    stcIrqSigninConfig.enIntSrc = USART_RX_TIMEOUT_INT_SRC;
    stcIrqSigninConfig.pfnCallback = &USART_RxTimeout_IrqCallback;
    (void)INTC_IrqSignIn(&stcIrqSigninConfig);
    NVIC_ClearPendingIRQ(stcIrqSigninConfig.enIRQn);
    NVIC_SetPriority(stcIrqSigninConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
    NVIC_EnableIRQ(stcIrqSigninConfig.enIRQn);

     /* Initialize DMA. */
     (void)DMA_Config();

     /* Initialize TMR0. */
     TMR0_Config(USART_TIMEOUT_BITS);

     /* Configure USART RX/TX pin. */
     GPIO_SetFunc(USART_RX_PORT, USART_RX_PIN, USART_RX_GPIO_FUNC);
     GPIO_SetFunc(USART_TX_PORT, USART_TX_PIN, USART_TX_GPIO_FUNC);

}

void App_uart2_init(void)
{

    stc_usart_uart_init_t stcUartInit;
    // stc_irq_signin_config_t stcIrqSigninConfig;

    FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_USART2, ENABLE);
    /* Initialize UART. */
    (void)USART_UART_StructInit(&stcUartInit);
    stcUartInit.u32ClockDiv = USART_CLK_DIV1;
    stcUartInit.u32CKOutput = USART_CK_OUTPUT_DISABLE;
    stcUartInit.u32Baudrate = 1000000;
    stcUartInit.u32OverSampleBit = USART_OVER_SAMPLE_8BIT;
  USART_UART_Init(USART_UNIT2, &stcUartInit, NULL);

    //  /* Register TX complete IRQ handler. */
    //  stcIrqSigninConfig.enIRQn = INT006_IRQn;
    //  stcIrqSigninConfig.enIntSrc = USART2_TX_CPLT_INT_SRC;
    //  stcIrqSigninConfig.pfnCallback = &USART2_TxComplete_IrqCallback;
    //  (void)INTC_IrqSignIn(&stcIrqSigninConfig);
    //  NVIC_ClearPendingIRQ(stcIrqSigninConfig.enIRQn);
    //  NVIC_SetPriority(stcIrqSigninConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
    //  NVIC_EnableIRQ(stcIrqSigninConfig.enIRQn);
 
    //  /* Register RX error IRQ handler. */
    //  stcIrqSigninConfig.enIRQn = INT007_IRQn;
    //  stcIrqSigninConfig.enIntSrc = USART2_RX_ERR_INT_SRC;
    //  stcIrqSigninConfig.pfnCallback = &USART2_RxError_IrqCallback;
    //  (void)INTC_IrqSignIn(&stcIrqSigninConfig);
    //  NVIC_ClearPendingIRQ(stcIrqSigninConfig.enIRQn);
    //  NVIC_SetPriority(stcIrqSigninConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
    //  NVIC_EnableIRQ(stcIrqSigninConfig.enIRQn);
 
    //  /* Register RX timeout IRQ handler. */
    //  stcIrqSigninConfig.enIRQn = INT008_IRQn;
    //  stcIrqSigninConfig.enIntSrc = USART2_RX_TIMEOUT_INT_SRC;
    //  stcIrqSigninConfig.pfnCallback = &USART2_RxTimeout_IrqCallback;
    //  (void)INTC_IrqSignIn(&stcIrqSigninConfig);
    //  NVIC_ClearPendingIRQ(stcIrqSigninConfig.enIRQn);
    //  NVIC_SetPriority(stcIrqSigninConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
    //  NVIC_EnableIRQ(stcIrqSigninConfig.enIRQn);
 
      /* Initialize TMR0. */
    //   TMR0_Config(USART_TIMEOUT_BITS);

     /* Configure USART RX/TX pin. */
     GPIO_SetFunc(USART_RX_PORT, USART_RX2_PIN, USART_RX_GPIO_FUNC);
     GPIO_SetFunc(USART_TX_PORT, USART_TX2_PIN, USART_TX_GPIO_FUNC);
}


void USART2_SendData(CM_USART_TypeDef *USARTx, uint8_t *data, uint16_t length)
{
    for (uint16_t i = 0; i < length; i++) {
        // 发送单个字节
        USART_WriteData(USARTx, data[i]);
    }
}

